D^3CTF 2019 ch1pfs wp
Category: RE
Solved: 1
拿到一堆文件,先运行一下,要求输入key,进到/test/,里面有文件,但是cat出来一堆乱码。
把CH1P_fs.ko拖到IDA里面看看,可以发现是自己写的一个文件系统,insmod的时候要一个key,key生成f_key,f_key在文件读写的时候进行异或加密。
然后到处看了看(strings rootfs.img、网上找了一下相关的代码、找到个假的getkey),明确给的各个文件的用途:
- CH1P_fs.ko 文件系统的驱动
- image CH1P_fs加密后的文件系统,系统启动后挂载到/test/目录
- waifu.png 明文图片,image里面也有一张
- 其他qemu所需的文件
至此,
明确解题思路:
- 因为是使用顺序的异或加解密,可以通过waifu.png的明密文对找出f_key
- 使用f_key查看其他文件或反推出key
Step1 找出png的明密文对
我patch了rootfs.img中的CH1P_fs.ko,将读取文件时的异或加密nop掉,直接输出raw的文件,使得我们能够定位密文在image中的位置。
png: 0x23bda0-0x732da0
png很大,在image文件中并不是完全连续的,中间还有一些数据,借助hexedit在patch过的文件系统上对比,可以将png密文完全提取出来(但是没有必要
Step2 根据明密文对恢复f_key
拿到明密文对直接异或即能得到f_key
1 | with open("ctf/waifu.png", "rb") as f: |
我只处理了前3*4096字节,发现key是一样的
Step3 解密其他数据
观察加解密的代码。如下图所示,还有个v8不知道,不过爆破4096次肯定能过出来
1 | def find_m(flag_c): |
flag还拿不到,其他数据都能够解密了,有个key文件,解密得到key: d3_CH1pfs!
,用key进入文件系统。
还有下一关:
1 | /test # cat make_flag.sh |
flag用enc加密过,但是并没有enc文件的影子,可能被删掉了,想到文件系统的删除并不是真·擦除,可能从image中恢复。
根据观察,image中只有两个大文件:png和busybox,统计了一下非零字节的个数,验证以上的想法
1 | with open("ctf/image", "rb") as f: |
对比发现文件系统里还有一个大文件,又因为enc是静态链接的,绝壁就是它了
如何提取:
- 修改record(不太熟悉linux文件系统,没有尝试
- 手动dump出raw的enc
我用了下面这种比较笨的方法
先拿f_key和ELF的开头四个字节定位到ELF的起始位置,手动从010editor中提取出来,中间夹杂着一些无用的数据。边用f_key恢复,拖到IDA里面查看,如果夹杂着没用的数据,汇编代码从那个位置开始很容易就能看出异常,微调即可。
1 | def re_enc_binary(): |
恢复出enc文件,拖到IDA中查看:
恢复符号表,可以发现逻辑十分简单:
又是异或而已,写出解密脚本:
1 | xor_key = [ |